home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / game / think / MUIMineSrc.lha / MUIMineSource / BTWindow.c next >
C/C++ Source or Header  |  1998-12-16  |  19KB  |  655 lines

  1. /*
  2.     MUI custom window class to display MUIMine best times
  3. */
  4.  
  5. #include "MUIMine.h"
  6. #include "MFStrings.h"
  7. #include "LevelData.h"
  8. #include "BTWindow.h"
  9.  
  10.  
  11. /*
  12.     instance data for BTWindow class
  13. */
  14. struct BTWindowData
  15. {
  16.     struct LevelDataList * Levels;  // level data to show best times for
  17.     int HighlightRank;              // rank to highlight in current level
  18.     ULONG DisplayedLevel;           // level whose best times are shown
  19.     Object * Times[3], * Names[3];  // text objects for times and names
  20.     Object * LevelCycle;            // cycle gadget to select level to show
  21.     STRPTR * CycleLabels;           // labels for the cycle gadget
  22. };
  23.  
  24.  
  25. /*
  26.     prototypes
  27. */
  28. static void SetLevel(struct BTWindowData * data, ULONG level);
  29. static void SetLevelIdx(struct BTWindowData * data, int idx);
  30. static void FillBestTimeText(struct BTWindowData * data, struct LevelData * pLevel);
  31. static void ResetBestTimes(struct LevelData * pLevel);
  32.  
  33. /*
  34.     function :    OM_NEW method handler for MFWindow class
  35. */
  36. static ULONG mNew(struct IClass *cl, Object *obj, struct opSet *msg)
  37. {
  38.     int i;
  39.     struct LevelData * pLevel;
  40.     struct LevelDataList * lList;
  41.     STRPTR * clabels, * pstr;
  42.     STRPTR closebuttlabel;
  43.     Object *times[3], *names[3], *lcycle,
  44.            *closebutt, *resetlbutt, *resetabutt;
  45.  
  46.     closebuttlabel = GetStr(MSG_CLOSEBUTT_LABEL);
  47.  
  48.     /*
  49.         get the level data list initialization attribute,
  50.         fail if not found or there are no levels in the list
  51.     */
  52.     lList = (struct LevelDataList *)GetTagData(MUIA_BTWindow_LevelList, NULL,
  53.                                                 msg->ops_AttrList);
  54.     if (lList == NULL  ||  lList->NumLevels == 0
  55.                        ||  lList->LevelList == NULL)
  56.     {
  57.         return NULL;
  58.     }
  59.  
  60.     /*
  61.         allocate the level cycle gadget label array,
  62.         fail if allocation fails
  63.     */
  64.     clabels = (STRPTR *)AllocVec((lList->NumLevels + 1) * sizeof(STRPTR), 0);
  65.     if (clabels == NULL)
  66.     {
  67.         return NULL;
  68.     }
  69.  
  70.     /*
  71.         initialize the cycle gadget's labels
  72.     */
  73.     for (i = lList->NumLevels, pLevel = lList->LevelList, pstr = clabels;
  74.          i > 0;
  75.          i--, pLevel++, pstr++)
  76.     {
  77.         *pstr = pLevel->Name;
  78.     }
  79.     *pstr = NULL;
  80.  
  81.     /*
  82.         create the root object for the window
  83.     */
  84.     obj = (Object *)DoSuperNew(cl, obj,
  85.             MUIA_Window_Title, GetStr(MSG_BTWINDOW_TITLE),
  86.             WindowContents, VGroup,
  87.                 Child, lcycle = CycleObject,
  88.                     MUIA_Cycle_Entries, clabels,
  89.                     MUIA_CycleChain, TRUE,
  90.                     MUIA_ShortHelp, GetStr(MSG_BTLEVELCYCLE_HELP),
  91.                     End,
  92.  
  93.                 Child, ColGroup(3),
  94.                     TextFrame,
  95.                     MUIA_Background, MUII_TextBack,
  96.                     MUIA_Group_SameWidth, FALSE,
  97.                     MUIA_ShortHelp, GetStr(MSG_BTLIST_HELP),
  98.  
  99.                     Child, TextObject,
  100.                         MUIA_Background, MUII_TextBack,
  101.                         MUIA_Text_Contents, "",
  102.                         End,
  103.                     Child, TextObject,
  104.                         MUIA_Background, MUII_TextBack,
  105.                         MUIA_Text_SetMax, TRUE,
  106.                         MUIA_Text_Contents, GetStr(MSG_TIMECOL_HEADING),
  107.                         End,
  108.                     Child, TextObject,
  109.                         MUIA_Background, MUII_TextBack,
  110.                         MUIA_Text_Contents, GetStr(MSG_NAMECOL_HEADING),
  111.                         End,
  112.  
  113.                     Child, TextObject,
  114.                         MUIA_Background, MUII_TextBack,
  115.                         MUIA_Text_SetMax, TRUE,
  116.                         MUIA_Text_Contents, "1. ",
  117.                         End,
  118.                     Child, times[0] = TextObject,
  119.                         MUIA_Background, MUII_TextBack,
  120.                         MUIA_Text_PreParse, "\033r",
  121.                         End,
  122.                     Child, names[0] = TextObject,
  123.                         MUIA_Background, MUII_TextBack,
  124.                         End,
  125.  
  126.                     Child, TextObject,
  127.                         MUIA_Background, MUII_TextBack,
  128.                         MUIA_Text_SetMax, TRUE,
  129.                         MUIA_Text_Contents, "2. ",
  130.                         End,
  131.                     Child, times[1] = TextObject,
  132.                         MUIA_Background, MUII_TextBack,
  133.                         MUIA_Text_PreParse, "\033r",
  134.                         End,
  135.                     Child, names[1] = TextObject,
  136.                         MUIA_Background, MUII_TextBack,
  137.                         End,
  138.  
  139.                     Child, TextObject,
  140.                         MUIA_Background, MUII_TextBack,
  141.                         MUIA_Text_SetMax, TRUE,
  142.                         MUIA_Text_Contents, "3. ",
  143.                         End,
  144.                     Child, times[2] = TextObject,
  145.                         MUIA_Background, MUII_TextBack,
  146.                         MUIA_Text_PreParse, "\033r",
  147.                         End,
  148.                     Child, names[2] = TextObject,
  149.                         MUIA_Background, MUII_TextBack,
  150.                         End,
  151.  
  152.                     End,
  153.  
  154.                 Child, HGroup,
  155.                     MUIA_Group_SameSize, TRUE,
  156.                     Child, closebutt = TextObject,
  157.                         ButtonFrame,
  158.                         MUIA_Background, MUII_ButtonBack,
  159.                         MUIA_Text_PreParse, "\033c",
  160.                         MUIA_Text_Contents, closebuttlabel + 2,
  161.                         MUIA_InputMode, MUIV_InputMode_RelVerify,
  162.                         MUIA_ControlChar, (LONG)*closebuttlabel,
  163.                         MUIA_Text_HiChar, (LONG)*closebuttlabel,
  164.                         MUIA_CycleChain, TRUE,
  165.                         MUIA_ShortHelp, GetStr(MSG_BTCLOSEBUTT_HELP),
  166.                         End,
  167.  
  168.                     Child, resetlbutt = TextObject,
  169.                         ButtonFrame,
  170.                         MUIA_Background, MUII_ButtonBack,
  171.                         MUIA_Text_Contents, GetStr(MSG_RESETLEVELBUTT_TEXT),
  172.                         MUIA_Text_PreParse, "\033c",
  173.                         MUIA_InputMode, MUIV_InputMode_RelVerify,
  174.                         MUIA_ShortHelp, GetStr(MSG_RESETLEVELBUTT_HELP),
  175.                         End,
  176.  
  177.                     Child, resetabutt = TextObject,
  178.                         ButtonFrame,
  179.                         MUIA_Background, MUII_ButtonBack,
  180.                         MUIA_Text_PreParse, "\033c",
  181.                         MUIA_Text_Contents, GetStr(MSG_RESETALLBUTT_TEXT),
  182.                         MUIA_InputMode, MUIV_InputMode_RelVerify,
  183.                         MUIA_ShortHelp, GetStr(MSG_RESETALLBUTT_HELP),
  184.                         End,
  185.  
  186.                     End,
  187.  
  188.                 End,
  189.  
  190.             TAG_MORE, msg->ops_AttrList);
  191.  
  192.     if (obj)
  193.     {
  194.         struct BTWindowData * data = INST_DATA(cl, obj);
  195.  
  196.         data->Levels = lList;
  197.         data->HighlightRank = (int)GetTagData(MUIA_BTWindow_HighlightRank,
  198.                                                 MUIV_BTWindow_HighlightRank_None,
  199.                                                 msg->ops_AttrList);
  200.         data->LevelCycle = lcycle;
  201.         data->CycleLabels = clabels;
  202.         data->DisplayedLevel = 0;
  203.  
  204.         for (i = 0; i < 3; i++)
  205.         {
  206.             data->Times[i] = times[i];
  207.             data->Names[i] = names[i];
  208.         }
  209.  
  210.         /*
  211.             make the close button the default object
  212.         */
  213.         SetAttrs(obj, MUIA_Window_DefaultObject, closebutt, TAG_DONE);
  214.  
  215.         /*
  216.             set the best times and names text for the current level
  217.         */
  218.         SetLevel(data, MUIV_BTWindow_Level_Current);
  219.  
  220.         /*
  221.             set up notifications
  222.         */
  223.         DoMethod(closebutt, MUIM_Notify, MUIA_Pressed, FALSE,
  224.                     obj, 3, MUIM_Set, MUIA_Window_CloseRequest, TRUE);
  225.  
  226.         DoMethod(lcycle, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime,
  227.                     obj, 3, MUIM_Set, MUIA_BTWindow_LevelIdx, MUIV_TriggerValue);
  228.  
  229.         DoMethod(resetlbutt, MUIM_Notify, MUIA_Pressed, FALSE,
  230.                     obj, 1, MUIM_BTWindow_ResetLevel);
  231.  
  232.         DoMethod(resetabutt, MUIM_Notify, MUIA_Pressed, FALSE,
  233.                     obj, 1, MUIM_BTWindow_ResetAll);
  234.     }
  235.     else
  236.     {
  237.         /*
  238.             if we could not create the window object then delete
  239.             the cycle gadget labels
  240.         */
  241.         FreeVec(clabels);
  242.     }
  243.  
  244.     /*
  245.         return the object (or NULL)
  246.     */
  247.     return (ULONG)obj;
  248. }
  249.  
  250.  
  251. /*
  252.     function :    OM_DELETE method handler for BTWindow class
  253. */
  254. static ULONG mDispose(struct IClass *cl, Object *obj, Msg msg)
  255. {
  256.     struct BTWindowData *data = INST_DATA(cl, obj);
  257.  
  258.     if (data->CycleLabels)
  259.     {
  260.         FreeVec((APTR)data->CycleLabels);
  261.     }
  262.  
  263.     return DoSuperMethodA(cl, obj, msg);
  264. }
  265.  
  266.  
  267. /*
  268.     function :    OM_SET method handler for BTWindow class
  269. */
  270. static ULONG mSet(struct IClass *cl, Object *obj, struct opSet * msg)
  271. {
  272.     struct BTWindowData *data = INST_DATA(cl,obj);
  273.     struct TagItem *tags, *tag;
  274.  
  275.     for (tags = msg->ops_AttrList; tag = NextTagItem(&tags); )
  276.     {
  277.         switch (tag->ti_Tag)
  278.         {
  279.             case MUIA_BTWindow_Level:
  280.             {
  281.                 SetLevel(data, (int)tag->ti_Data);
  282.                 break;
  283.             }
  284.  
  285.             case MUIA_BTWindow_LevelIdx:
  286.             {
  287.                 SetLevelIdx(data, (int)tag->ti_Data);
  288.                 break;
  289.             }
  290.         }
  291.     }
  292.  
  293.     return DoSuperMethodA(cl, obj, (APTR)msg);
  294. }
  295.  
  296. /*
  297.     function :    OM_GET method handler for BTWindow class
  298. */
  299. static ULONG mGet(struct IClass *cl, Object *obj, struct opGet * msg)
  300. {
  301.     struct BTWindowData *data = INST_DATA(cl, obj);
  302.     ULONG *store = msg->opg_Storage;
  303.  
  304.     if (msg->opg_AttrID == MUIA_BTWindow_Level)
  305.     {
  306.         *store = (ULONG)data->DisplayedLevel;
  307.         return TRUE;
  308.     }
  309.  
  310.     return DoSuperMethodA(cl, obj, (APTR)msg);
  311. }
  312.  
  313.  
  314.  
  315. /*
  316.     function :    MUIM_BTWindow_ResetLevel method handler for BTWindow class
  317. */
  318. static ULONG mResetLevel(struct IClass *cl, Object *obj, Msg msg)
  319. {
  320.     struct BTWindowData *data = INST_DATA(cl, obj);
  321.     struct LevelData * pLevel;
  322.     /*
  323.         check if there is a level displayed to be reset
  324.     */
  325.     pLevel = FindLevel(data->Levels, data->DisplayedLevel);
  326.     if (pLevel)
  327.     {
  328.         struct Object * app = NULL;
  329.         /*
  330.             get application object
  331.         */
  332.         DoMethod(obj, OM_GET, MUIA_ApplicationObject, &app);
  333.  
  334.         /*
  335.             query the reset
  336.         */
  337.         if (MUI_RequestA(app, obj, 0, GetStr(MSG_BTWINDOW_TITLE),
  338.                                       GetStr(MSG_YESNO_GADGETS),
  339.                                       GetStr(MSG_QUERY_RESETLEVEL),
  340.                                       NULL))
  341.         {
  342.             /*
  343.                 reset the best time data for this level and set
  344.                 the window's close request
  345.             */
  346.             ResetBestTimes(pLevel);
  347.             SetAttrs(obj, MUIA_Window_CloseRequest, TRUE, TAG_DONE);
  348.         }
  349.     }
  350.  
  351.     return 0;
  352. }
  353.  
  354.  
  355. /*
  356.     function :    MUIM_BTWindow_ResetAll method handler for BTWindow class
  357. */
  358. static ULONG mResetAll(struct IClass *cl, Object *obj, Msg msg)
  359. {
  360.     struct Object * app = NULL;
  361.     struct BTWindowData *data = INST_DATA(cl, obj);
  362.  
  363.     /*
  364.         get application object
  365.     */
  366.     DoMethod(obj, OM_GET, MUIA_ApplicationObject, &app);
  367.  
  368.     /*
  369.         query the reset
  370.     */
  371.     if (MUI_RequestA(app, obj, 0, GetStr(MSG_BTWINDOW_TITLE),
  372.                                   GetStr(MSG_YESNO_GADGETS),
  373.                                   GetStr(MSG_QUERY_RESETALL),
  374.                                   NULL))
  375.     {
  376.         /*
  377.             reset the best time for all levels then set the
  378.             window's close request attribute
  379.         */
  380.         int i;
  381.         struct LevelData * pLevel = data->Levels->LevelList;
  382.         for (i = data->Levels->NumLevels; i > 0; i--)
  383.         {
  384.             ResetBestTimes(pLevel++);
  385.         }
  386.  
  387.         SetAttrs(obj, MUIA_Window_CloseRequest, TRUE, TAG_DONE);
  388.     }
  389.  
  390.     return 0;
  391. }
  392.  
  393.  
  394. /*
  395.     function :    class dispatcher
  396. */
  397. SAVEDS ASM ULONG BTWindowDispatcher(
  398.         REG(a0) struct IClass *cl,
  399.         REG(a2) Object *obj,
  400.         REG(a1) Msg msg)
  401. {
  402.     switch (msg->MethodID)
  403.     {
  404.         case OM_NEW:     return mNew    (cl, obj, (APTR)msg);
  405.         case OM_DISPOSE: return mDispose(cl, obj, (APTR)msg);
  406.         case OM_SET:     return mSet    (cl, obj, (APTR)msg);
  407.         case OM_GET:     return mGet    (cl, obj, (APTR)msg);
  408.  
  409.         case MUIM_BTWindow_ResetLevel:
  410.             return mResetLevel(cl, obj, (APTR)msg);
  411.  
  412.         case MUIM_BTWindow_ResetAll:
  413.             return mResetAll(cl, obj, (APTR)msg);
  414.     }
  415.  
  416.     return DoSuperMethodA(cl, obj, msg);
  417. }
  418.  
  419.  
  420. /*
  421.     function :    sets the level shown to the given level, checks for the
  422.                   special value MUIV_BTWindow_Level_Current and sets the
  423.                   level to the current level if it exists or to the first
  424.                   levele in the list if there is no current level, if the
  425.                   level given is not a special value then searches the
  426.                   level list for the given level and if found then sets
  427.                   the level to the given level otherwise no action is taken
  428.  
  429.                   if a level is set the cycle gadget is set to that level and
  430.                   the text objects are filled with the best time data for the
  431.                   level
  432.  
  433.     parameters :  data = pointer to the BTWindowData
  434.                   level = the level to set to
  435.  
  436.     return :      none
  437. */
  438. static void SetLevel(struct BTWindowData * data, ULONG level)
  439. {
  440.     struct LevelData * pLevel;
  441.  
  442.     /*
  443.         check for special values
  444.     */
  445.     if (level == MUIV_BTWindow_Level_Current)
  446.     {
  447.         /*
  448.             set the level to the current level if it exists
  449.             otherwise set to the first level in the list
  450.         */
  451.         pLevel = FindCurrentLevel(data->Levels);
  452.         if (!pLevel)
  453.         {
  454.             pLevel = data->Levels->LevelList;
  455.         }
  456.     }
  457.     else
  458.     {
  459.         /*
  460.             level is not a special value, search for the given
  461.             level in the level list
  462.         */
  463.         pLevel = FindLevel(data->Levels, level);
  464.     }
  465.  
  466.     /*
  467.         check if we found a level to set window contents to
  468.     */
  469.     if (pLevel)
  470.     {
  471.         int idx;
  472.         struct LevelData * p;
  473.         ULONG useLevel = pLevel->Level;
  474.         /*
  475.             step through level list until we reach this level
  476.             counting the index along the way
  477.         */
  478.         for (idx = 0, p = data->Levels->LevelList;
  479.              idx < data->Levels->NumLevels;
  480.              idx++, p++)
  481.         {
  482.             if (p->Level == useLevel)
  483.             {
  484.                 break;
  485.             }
  486.         }
  487.  
  488.         /*
  489.             set the cycle gadget to the index of this level
  490.             do this without a notification so that the best
  491.             time text will not bell filled for a second time
  492.         */
  493.         SetAttrs(data->LevelCycle, MUIA_NoNotify, TRUE,
  494.                                    MUIA_Cycle_Active, idx,
  495.                                    TAG_DONE);
  496.  
  497.         /*
  498.             fill the best time text objects with this level's
  499.             best time data
  500.         */
  501.         FillBestTimeText(data, pLevel);
  502.     }
  503. }
  504.  
  505.  
  506. /*
  507.     function :    sets the best time text to the best time for the level
  508.                   at the given zero-based index in the level list
  509.                   the cycle gadget is not set here as this function is only
  510.                   called as a result of the cycle gadget active entry changing
  511.  
  512.     parameters :  data = pointer to the BTWindow data
  513.                   idx = index of level to set
  514.  
  515.     return :      none
  516. */
  517. static void SetLevelIdx(struct BTWindowData * data, int idx)
  518. {
  519.     /*
  520.         check for valid index
  521.     */
  522.     if (idx >= 0  &&  idx < data->Levels->NumLevels)
  523.     {
  524.         /*
  525.             fill the best time text objects with this level's
  526.             best time data
  527.         */
  528.         FillBestTimeText(data, &data->Levels->LevelList[idx]);
  529.     }
  530. }
  531.  
  532.  
  533. /*
  534.     function :    fills the best time text objects with the data from
  535.                   the given level
  536.  
  537.     parameters :  data = pointer to the BTWindowData
  538.                   pLevel = pointer to the LevelData
  539.  
  540.     return :      none
  541. */
  542. static void FillBestTimeText(struct BTWindowData * data, struct LevelData * pLevel)
  543. {
  544.     /*
  545.         check if the given level is different from the level
  546.         currently displayed
  547.     */
  548.     if (pLevel->Level != data->DisplayedLevel)
  549.     {
  550.         int i;
  551.         char timestr[12];
  552.         char namestr[BT_NAME_SIZE + 8];
  553.         struct BestTime * p;
  554.         int hiRank = -1;
  555.  
  556.         /*
  557.             if this is the game's current level then set the highlight rank
  558.         */
  559.         if (pLevel->Level == data->Levels->CurrentLevel)
  560.         {
  561.             hiRank = data->HighlightRank;
  562.         }
  563.  
  564.         /*
  565.             for each of the three best times for the level
  566.         */
  567.         for (i = 0, p = pLevel->BestTimes; i < 3; i++, p++)
  568.         {
  569.             /*
  570.                 check if best time for this rank has been set
  571.             */
  572.             if (p->Time > 0)
  573.             {
  574.                 /*
  575.                     if this is the highlighted rank the set the text for
  576.                     the rank to bold otherwise display it normally
  577.                 */
  578.                 if (i == hiRank)
  579.                 {
  580.                     sprintf(timestr, "\033b%d ", p->Time);
  581.                     sprintf(namestr, "\033b%s",  p->Name);
  582.                 }
  583.                 else
  584.                 {
  585.                     sprintf(timestr, "%d ", p->Time);
  586.                     strcpy(namestr, p->Name);
  587.                 }
  588.             }
  589.             else
  590.             {
  591.                 /*
  592.                     best time for this rank has not been set
  593.                 */
  594.                 strcpy(timestr, "- ");
  595.                 strcpy(namestr, "-");
  596.             }
  597.             /*
  598.                 set the text for this rank
  599.             */
  600.             SetAttrs(data->Times[i], MUIA_Text_Contents, timestr, TAG_DONE);
  601.             SetAttrs(data->Names[i], MUIA_Text_Contents, namestr, TAG_DONE);
  602.         }
  603.  
  604.         /*
  605.             set the displayed level for the window
  606.         */
  607.         data->DisplayedLevel = pLevel->Level;
  608.     }
  609. }
  610.  
  611.  
  612. /*
  613.     function :    resets the best time data for a level
  614.  
  615.     parameters :  pLevel = pointer to level to reset best times for
  616.  
  617.     return :      none
  618. */
  619. static void ResetBestTimes(struct LevelData * pLevel)
  620. {
  621.     int i;
  622.     struct BestTime * p;
  623.  
  624.     for (i = 0, p = pLevel->BestTimes; i < 3; i++, p++)
  625.     {
  626.         p->Time = -1;
  627.         p->Name[0] = 0;
  628.     }
  629. }
  630.  
  631.  
  632. /*
  633.     function :    creates the BTWindow MUI custom class
  634.  
  635.     return :      pointer to the created custom class or NULL
  636. */
  637. struct MUI_CustomClass * CreateBTWindowClass()
  638. {
  639.     return MUI_CreateCustomClass(NULL, MUIC_Window, NULL,
  640.                                        sizeof(struct BTWindowData),
  641.                                        BTWindowDispatcher);
  642. }
  643.  
  644. /*
  645.     function :    deletes of the BTWindow custom class
  646.  
  647.     parameters :  mcc = pointer to the BTWindow MUI_CustomClass to delete
  648. */
  649. void DeleteBTWindowClass(struct MUI_CustomClass * mcc)
  650. {
  651.     MUI_DeleteCustomClass(mcc);
  652. }
  653.  
  654.  
  655.